Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT: 상황에 따른 에러 핸들링 #16

Merged
merged 10 commits into from
Jun 7, 2024
Merged

FEAT: 상황에 따른 에러 핸들링 #16

merged 10 commits into from
Jun 7, 2024

Conversation

ittzggd
Copy link
Collaborator

@ittzggd ittzggd commented May 11, 2024

이슈 (번호도 함께 작성해주세요)

15

해당 사항 (중복 선택)

  • FEAT : 새로운 기능 추가 및 개선
  • FIX : 기존 기능 수정 및 정상 동작을 위한 간단한 추가, 수정사항
  • BUG : 버그 수정
  • REFACTOR : 결과의 변경 없이 코드의 구조를 재조정
  • TEST : 테스트 코드 추가
  • DOCS : 코드가 아닌 문서를 수정한 경우
  • REMOVE : 파일을 삭제하는 작업만 수행
  • RENAME : 파일 또는 폴더명을 수정하거나 위치(경로)를 변경
  • ETC : 이외에 다른 경우 - 어떠한 사항인지 작성해주세요.

반영 브랜치

ex) feat/login -> dev
feat/errorHandler/2

변경 사항

ex) 로그인 시, 구글 소셜 로그인 기능을 추가했습니다.

CustomError enum

  • Hane에서 발생할 수 있는 종류의 에러들을 선언한 에러 enum입니다
  • Error 프로토콜을 준수합니다
  • CustomError의 extension으로 errorDescription과 recoverySuggestion을 지정합니다. 해당 extension은 두 프로퍼티를 담고 있는 LocalizedError 프로토콜을 준수합니다
    • errorDescription: 어떤 에러인지에 대한 내용을 담고있습니다
    • recoverySuggestion : 해당 에러에 따른 사용자의 이후 행동을 제시합니다
    • 사용자에게 에러에 대한 alert를 띄워주는 경우, alert의 내용은 errorDescription과 recoverySuggestion으로 구성됩니다

ErrorHandler class

  • errorType: CustomError: 상황에 맞는 에러로 set 됩니다. 아무에러도 발생하지 않은 경우 기본값은 .none으로 설정됩니다.

  • showAlert: Bool: 사용자에게 에러에 대한 정보를 담은 alert의 present 여부입니다.

  • signInRequired: Bool: 재로그인이 필요한 에러 발생시, 로그인뷰로의 전환 여부를 나타내는 변수입니다. 추후 해당 변수는 UserDefualt로 대체될 예정입니다.

  • func errorFromHttpRequest(_ statusCode: Int?) throw : 200...299 구간을 제외한 statusCode가 반환되는 경우, 각 코드에 맞는 CustomError의 case를 throw합니다.

  • func verifyError(_ error: Error) async : throw된 에러들을 타입에 따라 구분합니다

    • status code로 구분가능한 에러 외에 클라이언트 레벨에서 throw 될 수 있는 에러들 역시 존재합니다. 선언한 customError 외에 다른 타입의 에러가 throw되는 경우 상황에 따라 CustomError 타입으로 전환합니다
    1. request body 디코딩에 실패하는 경우
    2. request url이 유효하지 않은 경우
    3. request 시점에 네트워크에 연결되지 않은 상태인 경우
    4. request에 대한 응답이 timeout인 경우
    5. 그외에 처리가 필요한 경우가 있다면 이야기 해주시면 감사하겠습니다!
  • func updateErrorView(): 에러 타입에 따른 뷰 업데이트 여부 및 어떤 방식의 뷰 업데이트인지 판별합니다.

###적용범위

  • 현재 homeVM에만 적용시킨 상태입니다. 다음과 같은 에러 핸들링 방식이 괜찮다면 추후 프로토콜화 작업 후 , 다른 메서드에도 적용 예정입니다!

@ittzggd ittzggd requested a review from HiHoi May 12, 2024 06:12
@ittzggd ittzggd self-assigned this May 12, 2024
@HiHoi
Copy link
Collaborator

HiHoi commented May 12, 2024

커스텀 에러 중
request 시점에 네트워크에 연결되지 않은 상태인 경우
request에 대한 응답이 timeout인 경우
부분은 저희가 고민이 많이 필요할 거 같습니다.
에러로 처리해서 로그인 화면으로 보여줄 수도 있지만 네트워크의 연결 상태를 계속 모니터링하면서 연결이 되면 요청을 하는 방법도 있지 않을까 싶네요. 하지만 이 방법은 api 요청 횟수를 보일 수 있어서 고민이 많이 필요하다 생각합니다.

Copy link
Collaborator

@HiHoi HiHoi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다! 코멘트 확인 부탁드립니다!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약 좀 더 발전시킨다면 에러가 일어나면 개발진 슬랙이나 이메일, 구글 스프레드에 바로 올려버리는 것도 좋아보이네요

Comment on lines 47 to 50
let statusCode = (response as? HTTPURLResponse)?.statusCode
guard statusCode == 200 else {
try ErrorHandler.shared.errorFromHttpRequest(statusCode)
throw CustomError.unknownError("\(statusCode)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요 부분이 이해가 잘 안갑니다. 코드가 200이 아닌 경우 그 상태코드를 들고 다시 errorFormHttpRequest를 이용해서 커스텀 에러에 속해있는지를 파악하는 거라 생각합니다. 이 부분에서 catch를 사용하지 않는 이유가 궁금합니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아뇨,errorFormHttpRequest를 이용해서 커스텀 에러에 속해있는지를 파악하는 것이 아닌 errorFormHttpRequest를 이용하여서 statuscode에 따라 발생한 에러를 custom 에러로 변환하는 과정입니다..! catch 후 에러를 핸들링 하는 과정을 한 곳에서 진행하는게 통일성 있을 듯 하여(요청한 vm class 내의 메서드에서) 해당 부분에서는 catch 하지 않고 다시 throw 후, 상위 메서드에서 catch 후 핸들링 하는 방식을 선택하였습니다. 만약 해당 request 메서드 내에서 catch 를 하게 되면, 상위 request를 호출한 메서드 내에서는 api request 시도에 실패하였다는 것을 알기 어려울 것 같습니다. 그렇게 될 경우, 요청 실패로인해 class내의 프로퍼티를 업데이트 하지 않아도 되는 경우에도 업데이트가 진행되는 등의 문제가 발생할 것 같습니다! 이와 같은이유로 다시 throw하게 처리하였는데 에러를 어디서 catch 하고 핸들링 하면 좋을지에 대해서는 추가적으로 고민해보겠습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

의도: 최상단으로 throw를 하기 위한 방법

의문: 책임의 소재

Comment on lines +49 to +62
func verifyError(_ error: Error) async {
switch error {
case DecodingError.dataCorrupted:
self.errorType = .decodeFailed
case URLError.timedOut:
self.errorType = .networkDisconnected
case URLError.networkConnectionLost:
self.errorType = .networkDisconnected
case is CustomError:
self.errorType = error as? CustomError ?? .none
default:
self.errorType = .unknownError(error.localizedDescription.description)
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 코드가 클라이언트 에러를 구분하는 책임을 맡은 만큼 함수 이름에서도 errorFromHttpRequest처럼 그 부분이 보였으면 좋겠습니다.

@ittzggd
Copy link
Collaborator Author

ittzggd commented May 14, 2024

코멘트 감사합니다:) 잘못 이해하고 계신 부분이 있어 말씁드립니다!request 시점에 네트워크에 연결되지 않은 상태인 경우와 request에 대한 응답이 timeout인 경우 로그인 화면을 보여주는 것이 아닌 네트워크가 연결되어있지 않거나 상태가 좋지 않은 상황(timeout)에 대한 alert를 띄워주는 방식입니다 :) 로그인 화면으로 돌아가는 경우는 token이 만료된 경우, unauthorized 에러가 발생하는 경우 뿐입니다!

@HiHoi
Copy link
Collaborator

HiHoi commented May 25, 2024

Conflict만 해결해주시면 Approve 하겠습니다!

@ittzggd ittzggd changed the base branch from refactor/home to dev June 3, 2024 09:58
@HiHoi
Copy link
Collaborator

HiHoi commented Jun 6, 2024

@ittzggd 충돌 한번만 확인해주시면 바로 승인하겠습니다!

Copy link
Collaborator

@HiHoi HiHoi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

충돌 고치기가 역시 번거롭네요. 얼른 Tuist를 ㅠㅠ 수고하셨습니다!!

@ittzggd ittzggd merged commit 9e907aa into dev Jun 7, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants